#! /bin/sh

# This script is intended to simulate loss and recovery of two
# EC2 nodes out of a pool of three, with an artarded operator
# that doesn't delete the schema directory of a stale node.

cleanup () \
  {
    erl -pa ../src -setcookie mega -sname killah -noshell -noinput -eval '
      "killah@" ++ Host = atom_to_list (node ()),
      rpc:call (list_to_atom ("flassy@" ++ Host), erlang, halt, []),
      rpc:call (list_to_atom ("turgy@" ++ Host), erlang, halt, []),
      rpc:call (list_to_atom ("warezy@" ++ Host), erlang, halt, []),
      rpc:call (list_to_atom ("inviso@" ++ Host), erlang, halt, [])
    ' -s erlang halt

    rm -rf Mnesia*flassy*
    rm -rf Mnesia*turgy*
    rm -rf Mnesia*warezy*
    rm -rf Mnesia*inviso*
  }

{

rm -rf Mnesia*flassy*
rm -rf Mnesia*turgy*
rm -rf Mnesia*warezy*
rm -rf Mnesia*inviso*

# first we start three nodes and get them running the same mnesia schema
# plus a fourth in a different group that nobodoy is supposed to see ...

erl -pa ../src -setcookie mega -sname inviso -schemafinder node_finder nodefinder -s combonodefinder -schemafinder group flass -s schemafinder -noshell -noinput -eval '
  true = register (hello, self ()),
  { atomic, ok } = delirium:heartbeat (),
  true = lists:keymember (schemafinder, 1, application:which_applications ()),
  receive { From, ruthere } -> From ! imok end,
  receive after infinity -> ok end
' -s erlang halt &

erl -hidden -pa ../src -setcookie mega -sname wazzup -noshell -noinput -eval '
  receive after 1000 -> ok end,
  "wazzup@" ++ Host = atom_to_list (node ()),
  pong = net_adm:ping (list_to_atom ("inviso@" ++ Host)),
  While = fun (F, W) -> case F () of false -> ok; 
                                     true -> receive after 1000 -> ok end,
                                             W (F, W)
                        end
          end,
  While (fun () -> rpc:call (list_to_atom ("inviso@" ++ Host), erlang, whereis, [ hello ]) =:= undefined end, While),
  Pid = rpc:call (list_to_atom ("inviso@" ++ Host), erlang, whereis, [ hello ]),
  true = erlang:is_pid (Pid),
  MRef = erlang:monitor (process, Pid),
  Pid ! { self (), ruthere },
  ok = receive imok -> ok; { 'DOWN', MRef, _, _, _ } -> flass end
' -s erlang halt || { cleanup; exit 1; }

erl -pa ../src -setcookie mega -sname flassy -schemafinder node_finder nodefinder -s combonodefinder -s schemafinder -noshell -noinput -eval '
  true = register (hello, self ()),
  { atomic, ok } = delirium:heartbeat (),
  true = lists:keymember (schemafinder, 1, application:which_applications ()),
  receive { From, ruthere } -> From ! imok end,
  receive after infinity -> ok end
' -s erlang halt &

erl -hidden -pa ../src -setcookie mega -sname wazzup -noshell -noinput -eval '
  receive after 1000 -> ok end,
  "wazzup@" ++ Host = atom_to_list (node ()),
  pong = net_adm:ping (list_to_atom ("flassy@" ++ Host)),
  While = fun (F, W) -> case F () of false -> ok; 
                                     true -> receive after 1000 -> ok end,
                                             W (F, W)
                        end
          end,
  While (fun () -> rpc:call (list_to_atom ("flassy@" ++ Host), erlang, whereis, [ hello ]) =:= undefined end, While),
  Pid = rpc:call (list_to_atom ("flassy@" ++ Host), erlang, whereis, [ hello ]),
  true = erlang:is_pid (Pid),
  MRef = erlang:monitor (process, Pid),
  Pid ! { self (), ruthere },
  ok = receive imok -> ok; { 'DOWN', MRef, _, _, _ } -> flass end
' -s erlang halt || { cleanup; exit 1; }

erl -pa ../src -setcookie mega -sname turgy -schemafinder node_finder nodefinder -s combonodefinder -s schemafinder -noshell -noinput -eval '
  true = register (hello, self ()),
  { atomic, ok } = delirium:heartbeat (),
  true = lists:keymember (schemafinder, 1, application:which_applications ()),
  receive { From, ruthere } -> From ! imok end,
  receive after infinity -> ok end
' -s erlang halt &

erl -hidden -pa ../src -setcookie mega -sname wazzup -noshell -noinput -eval '
  receive after 1000 -> ok end,
  "wazzup@" ++ Host = atom_to_list (node ()),
  pong = net_adm:ping (list_to_atom ("turgy@" ++ Host)),
  While = fun (F, W) -> case F () of false -> ok; 
                                     true -> receive after 1000 -> ok end,
                                             W (F, W)
                        end
          end,
  While (fun () -> rpc:call (list_to_atom ("turgy@" ++ Host), erlang, whereis, [ hello ]) =:= undefined end, While),
  Pid = rpc:call (list_to_atom ("turgy@" ++ Host), erlang, whereis, [ hello ]),
  true = erlang:is_pid (Pid),
  MRef = erlang:monitor (process, Pid),
  Pid ! { self (), ruthere },
  ok = receive imok -> ok; { 'DOWN', MRef, _, _, _ } -> flass end
' -s erlang halt || { cleanup; exit 1; }

erl -pa ../src -setcookie mega -sname warezy -schemafinder node_finder nodefinder -s combonodefinder -s schemafinder -noshell -noinput -eval '
  true = register (hello, self ()),
  { atomic, ok } = delirium:heartbeat (),
  true = lists:keymember (schemafinder, 1, application:which_applications ()),
  receive after 1000 -> ok end,
  length (mnesia:system_info (running_db_nodes)) =:= 2,
  { atomic, ok } = 
    mnesia:create_table (flass,
                         [ { disc_copies,
                             mnesia:system_info (running_db_nodes)  } ]),
  receive { From, ruthere } -> From ! imok end,
  receive after infinity -> ok end
' -s erlang halt &

erl -hidden -pa ../src -setcookie mega -sname wazzup -noshell -noinput -eval '
  receive after 1000 -> ok end,
  "wazzup@" ++ Host = atom_to_list (node ()),
  pong = net_adm:ping (list_to_atom ("warezy@" ++ Host)),
  While = fun (F, W) -> case F () of false -> ok; 
                                     true -> receive after 1000 -> ok end,
                                             W (F, W)
                        end
          end,
  While (fun () -> rpc:call (list_to_atom ("warezy@" ++ Host), erlang, whereis, [ hello ]) =:= undefined end, While),
  Pid = rpc:call (list_to_atom ("warezy@" ++ Host), erlang, whereis, [ hello ]),
  true = erlang:is_pid (Pid),
  MRef = erlang:monitor (process, Pid),
  Pid ! { self (), ruthere },
  ok = receive imok -> ok; { 'DOWN', MRef, _, _, _ } -> flass end
' -s erlang halt || { cleanup; exit 1; }

# now kill flassy and turgy 

erl -hidden -pa ../src -setcookie mega -sname killah -noshell -noinput -eval '
  "killah@" ++ Host = atom_to_list (node ()),
  rpc:call (list_to_atom ("flassy@" ++ Host), erlang, halt, []),
  rpc:call (list_to_atom ("turgy@" ++ Host), erlang, halt, []),
  { atomic, ok } = rpc:call (list_to_atom ("warezy@" ++ Host),
                             delirium,
                             condemn,
                             [ list_to_atom ("flassy@" ++ Host) ]),
  { atomic, ok } = rpc:call (list_to_atom ("warezy@" ++ Host),
                             delirium,
                             condemn,
                             [ list_to_atom ("turgy@" ++ Host) ]),
  { ok, Pid } = rpc:call (list_to_atom ("warezy@" ++ Host), 
                          delirium,
                          force_prune,
                          []),
  MonitorRef = erlang:monitor (process, Pid),
  receive
    { 'DOWN', MonitorRef, _Type, _Object, _Info } -> ok
  end,
  Warez = list_to_atom ("warezy@" ++ Host),
  [ Warez ] = rpc:call (Warez, mnesia, system_info, [ db_nodes ])
' -s erlang halt || { cleanup; exit 1; }

# now restart turgy

rm -rf Mnesia*turgy*

erl -pa ../src -setcookie mega -sname turgy -schemafinder node_finder nodefinder -s combonodefinder -s schemafinder -noshell -noinput -eval '
  true = register (hello, self ()),
  { atomic, ok } = delirium:heartbeat (),
  { atomic, ok } = mnesia:add_table_copy (flass, node (), ram_copies),
  true = lists:keymember (schemafinder, 1, application:which_applications ()),
  receive { From, ruthere } -> From ! imok end,
  receive after infinity -> ok end
' -s erlang halt &

erl -hidden -pa ../src -setcookie mega -sname wazzup -noshell -noinput -eval '
  receive after 1000 -> ok end,
  "wazzup@" ++ Host = atom_to_list (node ()),
  pong = net_adm:ping (list_to_atom ("turgy@" ++ Host)),
  While = fun (F, W) -> case F () of false -> ok; 
                                     true -> receive after 1000 -> ok end,
                                             W (F, W)
                        end
          end,
  While (fun () -> rpc:call (list_to_atom ("turgy@" ++ Host), erlang, whereis, [ hello ]) =:= undefined end, While),
  Pid = rpc:call (list_to_atom ("turgy@" ++ Host), erlang, whereis, [ hello ]),
  true = erlang:is_pid (Pid),
  MRef = erlang:monitor (process, Pid),
  Pid ! { self (), ruthere },
  ok = receive imok -> ok; { 'DOWN', MRef, _, _, _ } -> flass end
' -s erlang halt || { cleanup; exit 1; }

# now restart flassy ... *without* removing it's schema directory

erl -pa ../src -setcookie mega -sname flassy -schemafinder node_finder nodefinder -s combonodefinder -s schemafinder -noshell -noinput -eval '
  false = lists:keymember (schemafinder, 1, application:which_applications ()),
  Node = node (),
  { aborted, { node_not_running, Node } } = 
    mnesia:add_table_copy (flass, node (), ram_copies)
' -s erlang halt || { cleanup; exit 1; }

# oops, i'm an ardtard

rm -rf Mnesia*flassy*

erl -pa ../src -setcookie mega -sname flassy -schemafinder node_finder nodefinder -s combonodefinder -s schemafinder -noshell -noinput -eval '
  true = register (hello, self ()),
  { atomic, ok } = delirium:heartbeat (),
  { atomic, ok } = mnesia:add_table_copy (flass, node (), ram_copies),
  true = lists:keymember (schemafinder, 1, application:which_applications ()),
  receive { From, ruthere } -> From ! imok end,
  receive after infinity -> ok end
' -s erlang halt &

erl -hidden -pa ../src -setcookie mega -sname wazzup -noshell -noinput -eval '
  receive after 1000 -> ok end,
  "wazzup@" ++ Host = atom_to_list (node ()),
  pong = net_adm:ping (list_to_atom ("flassy@" ++ Host)),
  While = fun (F, W) -> case F () of false -> ok; 
                                     true -> receive after 1000 -> ok end,
                                             W (F, W)
                        end
          end,
  While (fun () -> rpc:call (list_to_atom ("flassy@" ++ Host), erlang, whereis, [ hello ]) =:= undefined end, While),
  Pid = rpc:call (list_to_atom ("flassy@" ++ Host), erlang, whereis, [ hello ]),
  true = erlang:is_pid (Pid),
  MRef = erlang:monitor (process, Pid),
  Pid ! { self (), ruthere },
  ok = receive imok -> ok; { 'DOWN', MRef, _, _, _ } -> flass end
' -s erlang halt || { cleanup; exit 1; }

cleanup

} 2>&1 > test-disaster.out

exit 0
